package org.vacoor.nothing.web.misc.codegen;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.vacoor.nothing.common.util.StringUtils;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 */
public class CrudCodeGenerator {
    private static final char DOT = '.';
    private static final char SLASH = '/';
    private static final String TPL_PATH = "/tpl/java";


    public static void main(String[] args) throws SQLException, IOException, TemplateException {
        /*
        String url = "jdbc:oracle:thin:@192.168.125.131:1521:ORCL";
        String username = "nothing";
        String password = "nothing";
        */
        final String url = "jdbc:oracle:thin:@192.168.1.123:1521:ORCL";
        final String username = "jiusu";
        final String password = "jiusu";
        final String schema = username.toUpperCase();
        // final String table = "TB_WAREHOUSE";
//        final String table = "TB_CAR_MODEL";
//        final String table = "TB_CAR_PLACE";
//        final String table = "TB_CAR_SERIES";
        final String table = "TB_CAR_MODEL";
        final String basePackage = "com.besture.jiusu";
        final File javaOutDir = new File("C:\\out\\java");
        final File resOutDir = new File("C:\\out\\resources");
        final EntityMapper mapper = new SimpleMapper();


        Connection conn = DriverManager.getConnection(url, username, password);
        ResultSet rs = conn.getMetaData().getImportedKeys(null, null, "TB_CAR_SERIES");
        // Jdbcs.printResultSet(rs);
        if (rs.next()) {
            String pktable_schem = rs.getString("PKTABLE_SCHEM");
            String pktable_name = rs.getString("PKTABLE_NAME");
            String pkcolumn_name = rs.getString("PKCOLUMN_NAME");
            String fktable_schem = rs.getString("FKTABLE_SCHEM");
            String fktable_name = rs.getString("FKTABLE_NAME");
            String fkcolumn_name = rs.getString("FKCOLUMN_NAME");
            int key_seq = rs.getInt("KEY_SEQ");
            System.out.println(key_seq + ": " + fktable_schem + "." + fktable_name + "(" + fkcolumn_name + ") REF " + pktable_schem + "." + pktable_name + "(" + pkcolumn_name + ")");
            //
            System.out.println();
        }
        System.exit(0);
        List<Jdbcs.DbTable> dbTables = Jdbcs.readTables(conn, schema, table, null);

        for (Jdbcs.DbTable dbTable : dbTables) {
            System.out.println(String.format("%s %s.%s", dbTable.type, dbTable.schema, dbTable.name));

            final List<Jdbcs.DbColumn> dbColumns = Jdbcs.readColumns(conn, dbTable.schema, dbTable.name, null);

            // 数据库映射信息
            final String entityName = mapper.getEntityName(dbTable.name);
            final MappedField[] mappedFields = Lists.transform(dbColumns, new Function<Jdbcs.DbColumn, MappedField>() {
                @Override
                public MappedField apply(Jdbcs.DbColumn input) {
                    String javaType = mapper.getJavaTypeFullName(input.name, input.type, input.sqlType, input.length, input.scale);
                    return new MappedField(StringUtils.underscoreToCamelCase(input.name, false), javaType, input.name);
                }
            }).toArray(new MappedField[dbColumns.size()]);

            MappedTable mappedTable = new MappedTable(entityName, dbTable.name, mappedFields);

            Configuration config = new Configuration();
            config.setTemplateLoader(new ClassTemplateLoader(CrudCodeGenerator.class, TPL_PATH));

            String pkg = basePackage;
            String entityPkg = pkg + ".entity";
            String daoPkg = pkg + ".dao";
            String daoImplPkg = daoPkg + ".impl";
            String servicePkg = pkg + ".service";
            String serviceImplPkg = servicePkg + ".impl";

            Map<String, Object> model = Maps.newHashMap();
            model.put("mappedTable", mappedTable);

            model.put("package", pkg);
            model.put("entityPackage", entityPkg);
            model.put("daoPackage", daoPkg);
            model.put("daoImplPackage", daoImplPkg);
            model.put("servicePackage", servicePkg);
            model.put("serviceImplPackage", serviceImplPkg);

            /*
            render(config.getTemplate("Entity.ftl"), model, new File(javaOutDir, toPath(entityPkg) + "/" + entityName + ".java"));
            render(config.getTemplate("CrudDao.ftl"), model, new File(javaOutDir, toPath(daoPkg) + "/" + entityName + "Dao.java"));
            render(config.getTemplate("CrudService.ftl"), model, new File(javaOutDir, toPath(servicePkg) + "/" + entityName + "Service.java"));

            render(config.getTemplate("MbtCrudMapper.ftl"), model, new File(resOutDir, toPath(daoPkg) + "/" + entityName + "Mapper.xml"));
            render(config.getTemplate("CrudServiceImpl.ftl"), model, new File(javaOutDir, toPath(serviceImplPkg) + "/" + entityName + "ServiceImpl.java"));

            String controllerPkg = pkg + ".controller.admin";
            model.put("controllerPackage", controllerPkg);
            render(config.getTemplate("EyController.ftl"), model, new File(javaOutDir, toPath(controllerPkg) + "/" + entityName + "Controller.java"));
            */

//            Reader reader = new InputStreamReader(CrudCodeGenerator.class.getResourceAsStream("/tpl/GridJs.ftl"));
            Reader reader = new InputStreamReader(CrudCodeGenerator.class.getResourceAsStream("/tpl/IndexJsp.ftl"));
            Template tpl = new Template("", reader, new Configuration());
            // tpl.process(model, new PrintWriter(System.out));
            String name = entityName.substring(0, 1).toLowerCase() + entityName.substring(1);
//            render(tpl, model, new File(resOutDir, name + ".js"));
            render(tpl, model, new File(resOutDir, "index.jsp"));
        }
    }

    protected static String toPath(String pkg) {
        return pkg != null ? pkg.replace(DOT, SLASH) : pkg;
    }

    protected static void render(Template tpl, Object model, File outFile) throws IOException, TemplateException {
//        if (outFile.exists()) {
//            System.err.println("Skip generate: File " + outFile + " is exists");
//        } else {
        ensureDirExists(outFile.getParentFile());
        System.out.println("Generate File: " + outFile);
        tpl.process(model, new FileWriter(outFile));
//        }
    }

    /**
     * 确信给定目录已经存在
     */
    protected static void ensureDirExists(File dir) {
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }
}
